package services

import (
	"encoding/json"
	"errors"
	"github.com/beego/beego/v2/client/orm"
	"time"
	"weiboxs.com/new_h_glasses/models"
	"weiboxs.com/new_h_glasses/utils"
)

type AllocationFormData struct {
}

func CreateAllocationNumber() string {
	//stat := utils.GetDateParse(time.Now().Format("2006-01-02"))
	//end := stat + 86400
	return models.CreatePk()
}

//新增调拨数据
func (a *AllocationFormData) AllocationCreateRecords(u *models.BackendUser, fromdep, targetdep int64, fromdep_name, targetdep_name, remarks string) (int64, error) {

	if fromdep == 0 || targetdep == 0 {
		return 0, errors.New("请选择需要调出调入的门店")
	}
	if fromdep == targetdep {
		return 0, errors.New("同一门店无须调用")
	}
	allocation := new(models.Allocation)
	allocation.Number = CreateAllocationNumber()
	allocation.CreateDepId = u.DepartmentId
	allocation.FromDepId = fromdep
	allocation.FromDepName = fromdep_name
	allocation.ToDepId = targetdep
	allocation.ToDepName = targetdep_name
	allocation.Remarks = remarks
	allocation.Auditing = 1
	allocation.OperatorName = u.RealName
	allocation.OperatorId = int64(u.Id)
	allocation.CreatedAt = time.Now().Unix()
	allocation.CreatedBy = allocation.OperatorName
	allocation.UpdatedAt = allocation.CreatedAt
	allocation.UpdatedBy = allocation.CreatedBy
	if _, err := orm.NewOrm().Insert(allocation); err != nil {
		return 0, err
	}
	return allocation.Id, nil
}

//修改盘点数据
func (a *AllocationFormData) AllocationUpdateRecords() error {

	allocation := new(models.Allocation)

	allocation.Auditing = 0
	allocation.UpdatedAt = allocation.CreatedAt
	allocation.UpdatedBy = allocation.CreatedBy

	fields, _ := utils.ReflectModelFields(allocation)

	to,_ := orm.NewOrm().Begin()

	if _, err := to.Update(allocation, fields...); err != nil {
		to.Rollback()
		return err
	}

	//删除原有的记录数据
	if _, err := to.QueryTable(models.StocksDataTableName()).Filter("allocation_id", allocation.Id).Delete(); err != nil {
		to.Rollback()
		return err
	}

	to.Commit()

	return nil
}

//保存调拨明细
type SubmitOrderData struct {
	Products      int64 `json:"products_id"`
	Middle        int64 `json:"middle_id"`
	Inventory     int64 `json:"inventory_id"`
	Snd           int64 `json:"snd_id"`
	AllocationNum int64 `json:"allocation_num"`
	Allocation    int64 `json:"allocation_id"`
}

func AllocationSubmitOrderData(data string) error {
	if len(data) <= 0 {
		return errors.New("明细数据为空")
	}
	order_data := make([]*SubmitOrderData, 0)
	if err := json.Unmarshal([]byte(data), &order_data); err != nil {
		return errors.New("明细解析出错" + err.Error())
	}
	if len(order_data) == 0 {
		return errors.New("明细数据为空")
	}
	//获取基本数据
	first := order_data[0]
	to,_ := orm.NewOrm().Begin()
	middle := new(models.AllocationMiddle)
	if first.Middle == 0 {
		middle.Products = &models.ErpProducts{Id: first.Products}
		middle.Allocation = &models.Allocation{Id: first.Allocation}
		if middle_id, err := to.Insert(middle); err != nil {
			to.Rollback()
			return err
		} else {
			middle.Id = middle_id
		}
	} else {
		middle.Id = first.Middle
	}
	if middle.Id == 0 {
		to.Rollback()
		return errors.New("关系数据失败")
	}
	//清除已有的
	if _, err := to.Raw("DELETE FROM "+models.AllocationDataTableName()+" WHERE allocation_id=? AND products_id=? AND middle_id=?", first.Allocation, first.Products, middle.Id).Exec(); err != nil {
		to.Rollback()
		return err
	}
	//处理明细数据
	var totalNumber int64
	into_data := make([]*models.AllocationData, 0)
	for k, _ := range order_data {
		s := order_data[k]
		d := new(models.AllocationData)
		d.Allocation = &models.Allocation{Id: s.Allocation}
		d.Products = &models.ErpProducts{Id: s.Products}
		d.Snd = &models.ErpProductsSnd{Id: s.Snd}
		d.MiddleId = middle.Id
		d.AllocationNum = s.AllocationNum
		d.Inventory = &models.ErpInventory{Id: s.Inventory}

		totalNumber += d.AllocationNum

		into_data = append(into_data, d)
	}

	if _, err := to.InsertMulti(len(into_data), into_data); err != nil {
		to.Rollback()
		return err
	}
	//更新中间表
	middle.PurchaseNum = totalNumber
	if _, err := to.Update(middle, "PurchaseNum"); err != nil {
		to.Rollback()
		return err
	}

	to.Commit()
	return nil
}

//删除中间表数据
func AllocationDeleteMiddleData(middle_id int64) error {
	to,_ := orm.NewOrm().Begin()

	middle := &models.AllocationMiddle{Id: middle_id}
	if err := to.Read(middle); err != nil {
		return err
	}
	if _, err := to.Delete(middle); err != nil { //删除中间数据
		return err
	}
	if _, err := to.Raw("DELETE FROM "+models.AllocationDataTableName()+" WHERE middle_id=?", middle_id).Exec(); err != nil { //删除明细表
		to.Rollback()
		return err
	}
	to.Commit()

	return nil
}

//按中间表ID获取退货明细
func (s *AllocationFormData) GetMiddleDataForEntry(middle_id int64) ([]*models.AllocationData, error) {
	if (middle_id == 0) {
		return nil, errors.New("参数错误")
	}
	entry_data := make([]*models.AllocationData, 0)

	orm.NewOrm().QueryTable(models.AllocationDataTableName()).RelatedSel("Products", "Inventory", "Inventory__Acceptance", "Snd").Filter("middle_id__eq", middle_id).Limit(-1).All(&entry_data)

	return entry_data, nil
}

//提交单据
func AllocationSubmitOrder(id int64, u *models.BackendUser) error {
	if id == 0 {
		return errors.New("参数错误")
	}
	allocation := models.GetAllocationById(id)
	if allocation.Id == 0 {
		return errors.New("没有找到单据")
	}
	if allocation.Auditing != 1 {
		return errors.New("单据不允许处理")
	}

	//获取产品数量
	o := orm.NewOrm()
	var totaoNumber int64
	o.Raw("SELECT SUM(purchase_num) as pnumber FROM "+models.AllocationMiddleTableName()+" WHERE allocation_id=?", id).QueryRow(&totaoNumber)

	allocation.Auditing = 2
	allocation.ProductNumber = totaoNumber
	if _, err := o.Update(allocation, "ProductNumber", "Auditing"); err != nil {
		return err
	}
	return nil
}

//退回单据
func ReturnAllocation(id int64, u *models.BackendUser) error {
	if id == 0 {
		return errors.New("参数错误")
	}
	allocation := models.GetAllocationById(id)
	if allocation.Id == 0 {
		return errors.New("没有找到单据")
	}
	if allocation.Auditing != 2 {
		return errors.New("单据不允许处理")
	}
	allocation.Auditing = 1
	if _, err := orm.NewOrm().Update(allocation, "Auditing"); err != nil {
		return err
	}
	return nil
}

//确认调拨[需要扣减库存]
func ConfirmAllocation(id int64, u *models.BackendUser) error {
	if id == 0 {
		return errors.New("参数错误")
	}
	allocation := models.GetAllocationById(id)
	if allocation.Id == 0 {
		return errors.New("没有找到单据")
	}
	if allocation.Auditing != 2 {
		return errors.New("单据不允许处理")
	}
	if allocation.FromDepId != u.DepartmentId {
		return errors.New("单据需要调拨门店确认")
	}
	allocation_data := models.AllocationDataList(id)
	if len(allocation_data) == 0 {
		return errors.New("没有可调拨明细")
	}
	to,_ := orm.NewOrm().Begin()
	flowingData := make([]*models.ErpFlowingData, 0)
	invSer := new(ErpInventoryService)
	for k, _ := range allocation_data {
		value := allocation_data[k]
		//判断库存是否正确
		if value.AllocationNum > value.Inventory.Inventory {
			to.Rollback()
			return errors.New("库存不足不允许调拨")
		}
		source_inventory := value.Inventory.Inventory
		if err := invSer.UpdateErpInventory(to, value.Inventory, (0 - value.AllocationNum)); err != nil {
			to.Rollback()
			return err
		}

		//设置流水明细
		flowing := new(models.ErpFlowingData)
		flowing.Typeid = 9 //调拨出库
		flowing.DepartmentId = allocation.FromDepId
		flowing.Products = value.Products
		flowing.Acceptance = value.Inventory.Acceptance
		flowing.InventoryId = value.Inventory.Id
		flowing.PrimaryStorageNum = source_inventory
		flowing.StorageNum = value.AllocationNum
		flowing.Snd = value.Snd
		flowing.PurchaseUpNo = allocation.Number
		flowingData = append(flowingData, flowing)
	}
	//写入流水明细
	flSer := new(ErpFlowingService)
	if err := flSer.SaveErpFlowingData(to, new(models.ErpFlowing), flowingData); err != nil {
		to.Rollback()
		return err
	}
	allocation.Auditing = 5
	if _, err := to.Update(allocation, "Auditing"); err != nil {
		to.Rollback()
		return err
	}
	to.Commit()
	return nil
}

//接收退回[把库存还原]
func WarehousingReturnAllocation(id int64, u *models.BackendUser) error {
	if id == 0 {
		return errors.New("参数错误")
	}
	allocation := models.GetAllocationById(id)
	if allocation.Id == 0 {
		return errors.New("没有找到单据")
	}
	if allocation.Auditing != 5 {
		return errors.New("单据不允许处理")
	}

	allocation_data := models.AllocationDataList(id)
	if len(allocation_data) == 0 {
		return errors.New("没有可调拨明细")
	}
	to,_ := orm.NewOrm().Begin()
	flowingData := make([]*models.ErpFlowingData, 0)
	invSer := new(ErpInventoryService)
	for k, _ := range allocation_data {
		value := allocation_data[k]
		//判断库存是否正确
		source_inventory := value.Inventory.Inventory
		if err := invSer.UpdateErpInventory(to, value.Inventory, value.AllocationNum); err != nil {
			to.Rollback()
			return err
		}
		//设置流水明细
		flowing := new(models.ErpFlowingData)
		flowing.Typeid = 11 //调拨退回
		flowing.DepartmentId = allocation.FromDepId
		flowing.Products = value.Products
		flowing.Acceptance = value.Inventory.Acceptance
		flowing.InventoryId = value.Inventory.Id
		flowing.PrimaryStorageNum = source_inventory
		flowing.StorageNum = value.AllocationNum
		flowing.Snd = value.Snd
		flowing.PurchaseUpNo = allocation.Number
		flowingData = append(flowingData, flowing)
	}
	//写入流水明细
	flSer := new(ErpFlowingService)
	if err := flSer.SaveErpFlowingData(to, new(models.ErpFlowing), flowingData); err != nil {
		to.Rollback()
		return err
	}
	allocation.Auditing = 2
	if _, err := to.Update(allocation, "Auditing"); err != nil {
		to.Rollback()
		return err
	}
	to.Commit()
	return nil
}

//接收调拨[接收门店库存增加]
func WarehousingConfirmAllocation(id int64, u *models.BackendUser) error {
	if id == 0 {
		return errors.New("参数错误")
	}
	allocation := models.GetAllocationById(id)
	if allocation.Id == 0 {
		return errors.New("没有找到单据")
	}
	if allocation.Auditing != 5 {
		return errors.New("单据不允许处理")
	}
	if allocation.ToDepId != u.DepartmentId {
		return errors.New("没有找到单据")
	}
	allocation_data := models.AllocationDataList(id)
	if len(allocation_data) == 0 {
		return errors.New("没有可调拨明细")
	}
	to,_ := orm.NewOrm().Begin()
	flowingData := make([]*models.ErpFlowingData, 0)
	invSer := new(ErpInventoryService)
	for k, _ := range allocation_data {
		value := allocation_data[k]

		inv := new(models.ErpInventory)

		inv.Products = value.Products
		inv.DepartmentId = allocation.ToDepId
		inv.ProductName = utils.ConvertPinyin(models.ProductGroupName(value.Products))
		inv.Acceptance = value.Inventory.Acceptance
		inv.Snd = value.Snd
		inv.Inventory = value.AllocationNum

		if hascode, err := models.CalculateInventoryHascode(inv); err != nil { //计算哈希值
			to.Rollback()
			return err
		} else {
			inv.Hascode = hascode
		}
		//判断库存是否正确
		var primaryStorageNum int64
		queryInv := invSer.QueryInventoryOne(0, inv.Hascode)
		if queryInv.Id > 0 { //存在则直接增加库存
			primaryStorageNum = queryInv.Inventory
			if err := invSer.UpdateErpInventory(to, queryInv, inv.Inventory); err != nil {
				to.Rollback()
				return err
			}
			inv.Id = queryInv.Id
		} else { //不存在则新增库存记录
			if err := invSer.InsertErpInventory(to, inv); err != nil {
				to.Rollback()
				return err
			}
		}
		//设置流水明细
		flowing := new(models.ErpFlowingData)
		flowing.Typeid = 10 //调拨入库
		flowing.DepartmentId = allocation.ToDepId
		flowing.Products = value.Products
		flowing.Acceptance = value.Inventory.Acceptance
		flowing.InventoryId = value.Inventory.Id
		flowing.PrimaryStorageNum = primaryStorageNum
		flowing.StorageNum = value.AllocationNum
		flowing.Snd = value.Snd
		flowing.PurchaseUpNo = allocation.Number
		flowingData = append(flowingData, flowing)
	}
	//写入流水明细
	flSer := new(ErpFlowingService)
	if err := flSer.SaveErpFlowingData(to, new(models.ErpFlowing), flowingData); err != nil {
		to.Rollback()
		return err
	}
	allocation.Auditing = 6
	if _, err := to.Update(allocation, "Auditing"); err != nil {
		to.Rollback()
		return err
	}
	to.Commit()
	return nil
}

//查看盘点信息
func AllocationDetail(id int64) (*models.Allocation, error) {

	var (
		err error
	)

	orm := orm.NewOrm()

	//获取主表信息
	allocation := new(models.Allocation)
	allocation.Id = id
	err = orm.Read(allocation)

	if err != nil {
		return nil, err
	}
	//获取副表信息
	allocationData := make([]*models.AllocationData, 0)
	_, err = orm.QueryTable(models.AllocationDataTableName()).Filter("allocation_id", id).All(&allocationData)

	if err != nil {
		return nil, err
	}
	allocation.AllocationData = allocationData

	return allocation, nil
}

//删除盘点数据
func AllocationDelete(id int64, depid int64) error {
	to,_ := orm.NewOrm().Begin()

	allocation := &models.Allocation{Id: id}

	if err := to.Read(allocation); err != nil { //查询是否存在记录信息
		to.Rollback()
		return err
	}
	if allocation.Auditing != 1 {
		return errors.New("调拨单据不允许删除")
	}
	if allocation.CreateDepId != depid {
		return errors.New("单据门店冲突不允许删除")
	}
	//删除主表
	if _, err := to.Raw("DELETE FROM "+models.AllocationTableName()+" WHERE id=?", id).Exec(); err != nil {
		to.Rollback()
		return err
	}
	//删除副表内容
	if _, err := to.Raw("DELETE FROM "+models.AllocationDataTableName()+" WHERE allocation_id=?", id).Exec(); err != nil {
		to.Rollback()
		return err
	}
	//删除中间表内容
	if _, err := to.Raw("DELETE FROM "+models.AllocationMiddleTableName()+" WHERE allocation_id=?", id).Exec(); err != nil {
		to.Rollback()
		return err
	}

	to.Commit()

	return nil
}
